package cn.edu.buu.hospital.web;

import cn.edu.buu.hospital.entity.Appointment;
import cn.edu.buu.hospital.entity.User;
import cn.edu.buu.hospital.entity.Department;
import cn.edu.buu.hospital.entity.Visit;
import cn.edu.buu.hospital.service.AppointmentService;
import cn.edu.buu.hospital.service.DepartmentService;
import cn.edu.buu.hospital.service.VisitService;
import com.github.pagehelper.PageInfo;
import jakarta.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.*;

/**
 * 预约记录控制类
 * 负责处理预约相关的HTTP请求，包括新增预约、查询预约、更新预约、删除预约等功能
 */
@Controller
@RequestMapping("/appointment")
public class AppointmentController {

    @Autowired
    private AppointmentService appointmentService; // 注入预约服务，处理预约相关的业务逻辑
    
    @Autowired
    private DepartmentService departmentService; // 注入科室服务，用于获取科室信息
    
    @Autowired
    private VisitService visitService; // 注入排班服务，用于获取排班信息

    /**
     * 跳转到新增预约页面
     * @param model 模型对象，用于传递数据到视图
     * @return 预约新增页面的视图路径
     */
    @GetMapping("/toAdd")
    public String toAdd(Model model) {
        // 获取所有科室
        List<Department> departmentList = departmentService.findAll();
        
        // 创建一个Map，用于存储科室ID和对应的排班列表
        Map<Long, List<Visit>> departmentVisitsMap = new HashMap<>();
        
        try {
            // 获取所有可预约的排班信息
            List<Visit> allVisits = visitService.findAll();
            
            // 按科室ID分组排班信息，便于前端展示
            for (Visit visit : allVisits) {
                if (visit.getDeptId() != null) {
                    departmentVisitsMap.computeIfAbsent(visit.getDeptId(), k -> new ArrayList<>()).add(visit);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        // 将科室列表和科室-排班映射关系添加到model中
        model.addAttribute("departmentList", departmentList);
        model.addAttribute("departmentVisitsMap", departmentVisitsMap);
        
        return "backend/appointment/add"; // 返回新增预约页面
    }

    /**
     * 新增预约
     * @param appointment 预约实体对象，包含预约信息
     * @param session HTTP会话对象，用于获取当前登录用户信息
     * @param model 模型对象，用于传递数据到视图
     * @return 成功则重定向到预约列表页面，失败则返回新增页面
     */
    @PostMapping("/add")
    public String add(Appointment appointment, HttpSession session, Model model) {
        // 从session中获取当前登录用户信息
        User loginUser = (User) session.getAttribute("loginAdmin");
        if (loginUser != null) {
            // 设置预约用户ID
            appointment.setUserid(loginUser.getUserid());
        } else {
            model.addAttribute("error", "请先登录");
            return "backend/appointment/add";
        }
        
        // 设置预约创建时间
        appointment.setCreatetime(LocalDateTime.now());
        // 设置预约状态为待就诊(0)
        appointment.setStatus(0);
        
        // 检查是否选择了排班
        if (appointment.getVisitid() == null) {
            model.addAttribute("error", "请选择排班");
            // 重新加载科室和排班数据
            List<Department> departmentList = departmentService.findAll();
            Map<Long, List<Visit>> departmentVisitsMap = new HashMap<>();
            List<Visit> allVisits = visitService.findAll();
            for (Visit visit : allVisits) {
                if (visit.getDeptId() != null) {
                    departmentVisitsMap.computeIfAbsent(visit.getDeptId(), k -> new ArrayList<>()).add(visit);
                }
            }
            model.addAttribute("departmentList", departmentList);
            model.addAttribute("departmentVisitsMap", departmentVisitsMap);
            return "backend/appointment/add";
        }
        
        // 生成唯一的预约编号（格式：AP+年月日时分秒+用户ID后四位）
        String number = "AP" + LocalDateTime.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))
                + loginUser.getUserid() % 10000;
        appointment.setNumber(number);
        
        // 调用服务层保存预约信息
        appointmentService.add(appointment);
        return "redirect:find"; // 重定向到预约列表页面
    }

    /**
     * 跳转到编辑预约页面
     * @param appointmentId 预约ID
     * @param model 模型对象，用于传递数据到视图
     * @return 预约编辑页面的视图路径
     */
    @GetMapping("/edit")
    public String edit(@RequestParam("appointmentId") Long appointmentId, Model model) {
        // 根据ID查询预约信息
        Appointment appointment = appointmentService.findById(appointmentId);
        model.addAttribute("appointment", appointment);
        return "backend/appointment/edit"; // 返回编辑页面
    }

    /**
     * 更新预约信息
     * @param appointment 包含更新信息的预约实体对象
     * @return 重定向到预约列表页面
     */
    @PostMapping("/update")
    public String update(Appointment appointment) {
        // 调用服务层更新预约信息
        appointmentService.modify(appointment);
        return "redirect:find"; // 重定向到预约列表页面
    }

    /**
     * 删除预约
     * @param appointmentId 预约ID
     * @return 重定向到预约列表页面
     */
    @GetMapping("/removeById")
    public String removeById(@RequestParam("appointmentId") Long appointmentId) {
        // 调用服务层删除指定ID的预约
        appointmentService.removeById(appointmentId);
        return "redirect:find"; // 重定向到预约列表页面
    }

    /**
     * 分页查询预约记录
     * @param pageNum 当前页码，默认为1
     * @param pageSize 每页显示的记录数，默认为5
     * @param patientName 患者姓名，用于搜索
     * @param deptId 科室ID，用于筛选
     * @param appointmentDate 预约日期，用于筛选
     * @param model 模型对象，用于传递数据到视图
     * @param session HTTP会话对象，用于获取当前登录用户信息
     * @return 预约列表页面的视图路径
     */
    @GetMapping("/find")
    public String find(
            @RequestParam(value = "pageNum", defaultValue = "1") int pageNum,
            @RequestParam(value = "pageSize", defaultValue = "5") int pageSize,
            @RequestParam(value = "patientName", required = false) String patientName,
            @RequestParam(value = "deptId", required = false) Long deptId,
            @RequestParam(value = "appointmentDate", required = false) String appointmentDate,
            Model model,
            HttpSession session) {
        
        // 创建查询条件对象
        Appointment condition = new Appointment();
        
        // 从session中获取当前登录用户信息
        User loginUser = (User) session.getAttribute("loginAdmin");
        
        // 如果是病人用户(type=1)，则只能查看自己的预约记录
        if (loginUser != null && loginUser.getType() == 1) {
            // 使用findByUserId方法查询用户的预约记录
            PageInfo<Appointment> pageInfo = appointmentService.findByUserId(pageNum, pageSize, loginUser.getUserid(), condition);
            model.addAttribute("pageInfo", pageInfo);
            model.addAttribute("patientName", loginUser.getUsername());
            model.addAttribute("deptId", deptId);
            
            // 加载部门列表供下拉选择
            List<Department> deptList = departmentService.findAll();
            model.addAttribute("deptList", deptList);
            
            return "backend/appointment/list";
        } else {
            // 非病人用户可以按患者姓名搜索
            if (patientName != null && !patientName.isEmpty()) {
                condition.setPatientName(patientName);
            }
        }
        
        // 添加科室ID到查询条件
        if (deptId != null) {
            // 由于科室ID在关联的visit表中，需要设置到visit对象中
            Visit visit = new Visit();
            visit.setDeptId(deptId);
            condition.setVisit(visit);
        }
        
        // 调用service层查询方法，获取分页数据
        PageInfo<Appointment> pageInfo = appointmentService.find(pageNum, pageSize, condition);
        
        // 将查询结果和科室列表添加到model中
        model.addAttribute("pageInfo", pageInfo);
        model.addAttribute("departmentList", departmentService.findAll());
        
        // 返回预约列表页面
        return "backend/appointment/list"; // 返回预约列表页面
    }

    /**
     * 确认预约
     * @param appointmentId 预约ID
     * @param model 模型对象，用于传递成功信息到视图
     * @return 重定向到预约列表页面
     */
    @GetMapping("/confirm")
    public String confirm(@RequestParam("appointmentId") Long appointmentId, Model model) {
        // 调用服务层确认预约
        appointmentService.confirmAppointment(appointmentId);
        model.addAttribute("success", "预约已确认，支付记录已生成，请提醒患者及时支付");
        return "redirect:find"; // 重定向到预约列表页面
    }

    /**
     * 取消预约
     * @param appointmentId 预约ID
     * @return 重定向到预约列表页面
     */
    @GetMapping("/cancel")
    public String cancel(@RequestParam("appointmentId") Long appointmentId) {
        // 调用服务层取消预约
        appointmentService.cancelAppointment(appointmentId);
        return "redirect:find"; // 重定向到预约列表页面
    }
}